<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Compile Conditions</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
	tex: {
		inlineMath: '$', '$'], ['\\(', '\\)'
	},
	svg: {
		fontCache: 'global'
	}
};
</script>
<script type="text/javascript" id="MathJax-script" async
	src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>

<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Compile Conditions' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../inform7n.html">Inform7</a></li><li><a href="index.html">imperative</a></li><li><a href="index.html#2">Chapter 2: Values</a></li><li><b>Compile Conditions</b></li></ul></div>
<p class="purpose">To compile Inter code to test a condition.</p>

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. </b>In fact almost all of the work is delegated to more potent routines elsewhere.
Much of <a href="4-cs.html" class="internal">Chapter 4: Propositions</a> is really dedicated to this.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">CompileConditions::compile</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">CompileConditions::compile</span></span>:<br/>Compile Values - <a href="2-cv.html#SP6_1_1">&#167;6.1.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">value_holster</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">cond</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PluginCalls::compile_condition</span><span class="plain-syntax">(</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">cond</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_type</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TEST_PROPOSITION_NT:</span>
<span class="plain-syntax">            </span><a href="4-cp.html#SP1" class="function-link"><span class="function-syntax">CompilePropositions::to_test_as_condition</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">,</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">Specifications::to_proposition</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">));</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOGICAL_TENSE_NT:</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Chronology::compile_past_tense_condition</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOGICAL_NOT_NT:</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-cc.html#SP1_1" class="named-paragraph-link"><span class="named-paragraph">Compile a logical negation</span><span class="named-paragraph-number">1.1</span></a></span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOGICAL_AND_NT:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOGICAL_OR_NT:</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-cc.html#SP1_2" class="named-paragraph-link"><span class="named-paragraph">Compile a logical operator</span><span class="named-paragraph-number">1.2</span></a></span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TEST_VALUE_NT:</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Specifications::is_description</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">                </span><span class="comment-syntax"> purely for problem recovery:</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">EmitCode::val_number</span><span class="plain-syntax">(1);</span>
<span class="plain-syntax">            } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">                </span><a href="2-cv.html#SP5" class="function-link"><span class="function-syntax">CompileValues::to_code_val</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TEST_PHRASE_OPTION_NT:</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-cc.html#SP1_3" class="named-paragraph-link"><span class="named-paragraph">Compile a phrase option test</span><span class="named-paragraph-number">1.3</span></a></span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP1_1" class="paragraph-anchor"></a><b>&#167;1.1. </b>An easy case, running straight out to Inter operators:
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile a logical negation</span><span class="named-paragraph-number">1.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::no_children</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">) != </span><span class="constant-syntax">1</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Compiled malformed LOGICAL_NOT_NT"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">NOT_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        </span><a href="2-cv.html#SP5" class="function-link"><span class="function-syntax">CompileValues::to_code_val</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cc.html#SP1">&#167;1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP1_2" class="paragraph-anchor"></a><b>&#167;1.2. </b>An easy case, running straight out to Inter operators:
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile a logical operator</span><span class="named-paragraph-number">1.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::no_children</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">) != </span><span class="constant-syntax">2</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Compiled malformed logical operator"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">left_operand</span><span class="plain-syntax"> = </span><span class="identifier-syntax">cond</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">right_operand</span><span class="plain-syntax"> = </span><span class="identifier-syntax">cond</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">left_operand</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">right_operand</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Compiled CONDITION/AND with LHS operands"</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">, </span><span class="identifier-syntax">LOGICAL_AND_NT</span><span class="plain-syntax">)) </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">AND_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">, </span><span class="identifier-syntax">LOGICAL_OR_NT</span><span class="plain-syntax">)) </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">OR_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        </span><a href="2-cv.html#SP5" class="function-link"><span class="function-syntax">CompileValues::to_code_val</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">left_operand</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><a href="2-cv.html#SP5" class="function-link"><span class="function-syntax">CompileValues::to_code_val</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">right_operand</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cc.html#SP1">&#167;1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP1_3" class="paragraph-anchor"></a><b>&#167;1.3. </b>Phrase options are stored as bits in a 16-bit map, so that each individual
option is a power of two from \(2^0\) to \(2^15\). We test if this is valid by
performing logical-and against the Inter local variable <span class="extract"><span class="extract-syntax">phrase_options</span></span>, which
exists if and only if the enclosing Inter routine takes phrase options. The
type-checker won't allow these specifications to be compiled anywhere else.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile a phrase option test</span><span class="named-paragraph-number">1.3</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">BITWISEAND_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">po</span><span class="plain-syntax"> = </span><a href="3-lv.html#SP5" class="function-link"><span class="function-syntax">LocalVariables::options_parameter</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">po</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no phrase options exist in this frame"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">inter_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">po_s</span><span class="plain-syntax"> = </span><a href="3-lv.html#SP1" class="function-link"><span class="function-syntax">LocalVariables::declare</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">po</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">EmitCode::val_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">po_s</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">EmitCode::val_number</span><span class="plain-syntax">((</span><span class="identifier-syntax">inter_ti</span><span class="plain-syntax">) </span><span class="identifier-syntax">Annotations::read_int</span><span class="plain-syntax">(</span><span class="identifier-syntax">cond</span><span class="plain-syntax">, </span><span class="identifier-syntax">phrase_option_ANNOT</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cc.html#SP1">&#167;1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>We need a mechanism for keeping track of the callings made in a condition,
and here it is. An issue here is that they generally have a scope extending
beyond that condition, and can't be left with kind-unsafe (or no) values. For
example, if:
</p>

<blockquote>
    <p>if a device (called the mechanism) is switched on: ...</p>
</blockquote>

<p class="commentary">turns out false, then "mechanism" has to be safely defused to some typesafe value.
So, then, the model is that if some part of Inform wants to compile a condition
which may involve callings, it should call <a href="2-cc.html#SP3" class="internal">CompileConditions::begin</a> first,
then notify us with <a href="2-cc.html#SP4" class="internal">CompileConditions::add_calling</a> of any local being used
as a calling, and then <a href="2-cc.html#SP5" class="internal">CompileConditions::end</a> when the code is done.
</p>

<p class="commentary">Callings arise from variables in predicate calculus, and there can only be 26
of those, so the following looks excessive. Well, so it is, of course: Inform
code in the wild never makes more than about three callings in any one condition.
But note that these condition sessions can be nested: you can begin a second
one inside the first, provided that you end it before you end the first one.
</p>

<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_CALLINGS_IN_MATCH</span><span class="plain-syntax"> </span><span class="constant-syntax">128</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax"> = -1;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">callings_session_number</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_CALLINGS_IN_MATCH</span><span class="plain-syntax">];</span>
<span class="reserved-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">callings_in_condition</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_CALLINGS_IN_MATCH</span><span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>The basic strategy here is to compile this:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    ((</span><span class="identifier-syntax">condition</span><span class="plain-syntax"> </span><span class="identifier-syntax">setting</span><span class="plain-syntax"> </span><span class="identifier-syntax">C1</span><span class="plain-syntax">, ..., </span><span class="identifier-syntax">Ci</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">C1</span><span class="plain-syntax"> = </span><span class="reserved-syntax">default</span><span class="plain-syntax">, </span><span class="identifier-syntax">C2</span><span class="plain-syntax"> = </span><span class="reserved-syntax">default</span><span class="plain-syntax">, ..., </span><span class="identifier-syntax">Ci</span><span class="plain-syntax"> = </span><span class="reserved-syntax">default</span><span class="plain-syntax">))</span>
</pre>
<p class="commentary">using the short-circuit property of <span class="extract"><span class="extract-syntax">OR_BIP</span></span>: if the condition evaluates to false,
and therefore there is no consistent set of values written into the calling
variables <span class="extract"><span class="extract-syntax">C1</span></span> to <span class="extract"><span class="extract-syntax">Ci</span></span>, then we evaluate the second clause, and set all of the
variables to default values for their kinds. In particular, if the condition
fails halfway, with some callings set and some not, they are all defaulted out,
so that you can never see partial results.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">CompileConditions::begin</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">CompileConditions::begin</span></span>:<br/>Matching Action Patterns - <a href="2-map.html#SP3_3">&#167;3.3</a><br/>Deciding to Defer - <a href="4-dtd.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">OR_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>Each variable records which "session" it belongs to, since there can be
multiple sessions happening at once:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">CompileConditions::add_calling</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">CompileConditions::add_calling</span></span>:<br/>Matching Action Patterns - <a href="2-map.html#SP7">&#167;7</a><br/>Deciding to Defer - <a href="4-dtd.html#SP8_1">&#167;8.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no PM session"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax"> == </span><span class="constant-syntax">MAX_CALLINGS_IN_MATCH</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">StandardProblems::sentence_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">BelievedImpossible</span><span class="plain-syntax">),</span>
<span class="plain-syntax">        </span><span class="string-syntax">"that makes too complicated a condition to test"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="string-syntax">"with all of those clauses involving 'called' values."</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">callings_session_number</span><span class="plain-syntax">[</span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax">] = </span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">callings_in_condition</span><span class="plain-syntax">[</span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">lvar</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>Now for the second operand of the <span class="extract"><span class="extract-syntax">OR_BIP</span></span>. If there weren't any callings,
we just compile <span class="extract"><span class="extract-syntax">false</span></span>. (It looks wasteful to have compiled "if (... or false)",
but in that event the use of <span class="extract"><span class="extract-syntax">OP_BIP</span></span> will be optimised out later: see
<a href="../pipeline-module/6-eros.html" class="internal">Eliminate Redundant Operations Stage (in pipeline)</a>.) If there were callings,
we default them.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">CompileConditions::end</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">CompileConditions::end</span></span>:<br/>Matching Action Patterns - <a href="2-map.html#SP3_3">&#167;3.3</a><br/>Deciding to Defer - <a href="4-dtd.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"unstarted PM session"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">NC</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">x</span><span class="plain-syntax"> = </span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax">, </span><span class="identifier-syntax">downs</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">x</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">callings_session_number</span><span class="plain-syntax">[</span><span class="identifier-syntax">x</span><span class="plain-syntax">-1] == </span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">NC</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">x</span><span class="plain-syntax">--;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">NC</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">EmitCode::val_false</span><span class="plain-syntax">();</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="2-cc.html#SP5_1" class="named-paragraph-link"><span class="named-paragraph">Set the callings in this session to default values for their kinds</span><span class="named-paragraph-number">5.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax">--;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">downs</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) { </span><span class="identifier-syntax">downs</span><span class="plain-syntax">--; </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">(); }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5_1" class="paragraph-anchor"></a><b>&#167;5.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Set the callings in this session to default values for their kinds</span><span class="named-paragraph-number">5.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">SEQUENTIAL_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">(); </span><span class="identifier-syntax">downs</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">NM</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">inner_downs</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">callings_session_number</span><span class="plain-syntax">[</span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax">-1] == </span><span class="identifier-syntax">current_session_number</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">NM</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lvar</span><span class="plain-syntax"> = </span><span class="identifier-syntax">callings_in_condition</span><span class="plain-syntax">[</span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax">-1];</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">NM</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">NC</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">SEQUENTIAL_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">(); </span><span class="identifier-syntax">inner_downs</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">STORE_BIP</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">inter_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lvar_s</span><span class="plain-syntax"> = </span><a href="3-lv.html#SP1" class="function-link"><span class="function-syntax">LocalVariables::declare</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">EmitCode::ref_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">lvar_s</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><a href="3-lv.html#SP24" class="function-link"><span class="function-syntax">LocalVariables::kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">K</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax">                (</span><span class="identifier-syntax">Kinds::Behaviour::is_object</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">)) ||</span>
<span class="plain-syntax">                (</span><span class="identifier-syntax">Kinds::Behaviour::definite</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax">                (</span><span class="identifier-syntax">DefaultValues::val</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">,</span>
<span class="plain-syntax">                    </span><span class="string-syntax">"'called' value"</span><span class="plain-syntax">) != </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">))</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">EmitCode::val_false</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">callings_in_condition_sp</span><span class="plain-syntax">--;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">inner_downs</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) { </span><span class="identifier-syntax">inner_downs</span><span class="plain-syntax">--; </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">(); }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">EmitCode::val_false</span><span class="plain-syntax">();</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cc.html#SP5">&#167;5</a>.</li></ul>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="2-cl.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-im.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-cv.html">cv</a></li><li class="progresssection"><a href="2-cr.html">cr</a></li><li class="progresssection"><a href="2-cl.html">cl</a></li><li class="progresscurrent">cc</li><li class="progresssection"><a href="2-map.html">map</a></li><li class="progresssection"><a href="2-mgap.html">mgap</a></li><li class="progresschapter"><a href="3-sf.html">3</a></li><li class="progresschapter"><a href="4-cs.html">4</a></li><li class="progresschapter"><a href="5-cbal.html">5</a></li><li class="progressnext"><a href="2-map.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

